【小ネタ】[OpenCV] 動画表示の時に画面にFPSとフレーム数を表示するクラスを作ってみました
1 はじめに
CX事業本部の平内(SIN)です。
機械学習によって動画を処理する場合、推論等による処理時間で、フレームレートが下がってしまう場合がありま。このような時、1つの指標になるのがFPSです。
要件に適応出来ているかどうかは、FPSはいくら出ているかで表現できます。
そして、よく見られるのが下のようなものです。画面の隅に、フレーム数とFPSが表示されています。
今回は、このような表示のためのクラスを作ってみました。コードの内容は、ネット上で広く利用されているものと同じです。
2 コード
FPS表示を担う部分を、DispFpsクラスとしました。
コンストラクタで、表示の諸元(色、フォント、サイズなど)を定義しています。
dispFps.py
from timeit import default_timer as timer import cv2 class DispFps(): def __init__(self): # 表示関連定義 self.__width = 80 self.__height = 20 self.__font_size = 0.4 self.__font_width = 1 self.__font_style = cv2.FONT_HERSHEY_COMPLEX self.__font_color = (255, 255, 255) self.__background_color = (0, 0, 0) # フレーム数カウント用変数 self.__frame_count = 0 # FPS計算用変数 self.__accum_time = 0 self.__curr_fps = 0 self.__prev_time = timer() self.__str = "FPS: " def __calc(self): # フレーム数更新 self.__frame_count += 1 # FPS更新 self.__curr_time = timer() self.__exec_time = self.__curr_time - self.__prev_time self.__prev_time = self.__curr_time self.__accum_time = self.__accum_time + self.__exec_time self.__curr_fps = self.__curr_fps + 1 if self.__accum_time > 1: self.__accum_time = self.__accum_time - 1 self.__str = "FPS: " + str(self.__curr_fps) self.__curr_fps = 0 def __disp(self, frame, str, x1, y1, x2, y2): cv2.rectangle(frame, (x1, y1), (x2, y2), self.__background_color, -1) cv2.putText(frame, str, (x1 + 5, y2 - 5), self.__font_style, self.__font_size, self.__font_color, self.__font_width) def disp(self, frame): # 表示内容計算 self.__calc() # フレーム数(左上に表示する) self.__disp(frame, str(self.__frame_count), 0, 0, x2 = self.__width, y2 = self.__height) # FPS(右上に表示する) screen_width = int(frame.shape[1]) self.__disp(frame, self.__str, screen_width - self.__width, 0, screen_width, self.__height)
上記のクラスを利用している例です。
動画処理するループに入る前に、DispFpsのインスタンスを生成し、ループの中で、disp()を呼ぶだけです。
なお、ループの中で呼ばれているtime.sleep(0.8)は、推論処理などを模擬したダミーのウエイト処理です。
index.py
import cv2 import time from dispFps import DispFps # Webカメラ DEVICE_ID = 0 WIDTH = 800 HEIGHT = 600 FPS = 24 def main(): cap = cv2.VideoCapture (DEVICE_ID) # フォーマット・解像度・FPSの設定 cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT) cap.set(cv2.CAP_PROP_FPS, FPS) # フォーマット・解像度・FPSの取得 width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) fps = cap.get(cv2.CAP_PROP_FPS) print("fps:{} width:{} height:{}".format(fps, width, height)) # [DispFps]インスタンス生成 dispFps = DispFps() while True: # カメラ画像取得 _, frame = cap.read() if(frame is None): continue # 擬似的なウエイト time.sleep(0.8) # [DispFps]計算及び表示 dispFps.disp(frame) # 画像表示 cv2.imshow('frame', frame) # 'q'をタイプされたらループから抜ける if cv2.waitKey(1) & 0xFF == ord('q'): break # VideoCaptureオブジェクト破棄 cap.release() cv2.destroyAllWindows() if __name__ == '__main__': main()
3 実行結果
time.sleep()に与えるウエイト値を変えてみた場合の、FPS表示は、下記のようになりました。
実装上、1FPS以上遅い場合は、1となってしまうことにご注意下さい。
ウエイト | FPS |
---|---|
0.01 | 24 |
0.05 | 12〜13 |
0.08 | 9〜10 |
0.1 | 6〜7 |
0.15 | 6 |
0.2 | 4 |
0.5 | 2 |
0.8 | 1 |
1.0 | 1 |
2.0 | 1 |
4 最後に
このクラスで軽易にFPS表示出来るようになれば、作業が捗るかも知れません・・・